package com.niiwoo.civet.trade.service.local.kaola;


import com.alibaba.dubbo.config.annotation.Reference;
import com.niiwoo.activity.event.enums.ProjectStatusEventEnum;
import com.niiwoo.activity.event.enums.ProjectSubStatusEventEnum;
import com.niiwoo.activity.stage.enums.prize.UserPrizeUseSceneEnum;
import com.niiwoo.civet.account.dto.common.BankCardDTO;
import com.niiwoo.civet.account.dto.request.AddThirdBillRequestDTO;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.enums.BillSecondSubjectEnum;
import com.niiwoo.civet.account.enums.BillUserTypeEnum;
import com.niiwoo.civet.account.enums.InoutTypeEnum;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.NiiwooBillDubboService;
import com.niiwoo.civet.account.service.bankcard.BankCardDubboService;
import com.niiwoo.civet.trade.constant.KaolaRepayFailMessageList;
import com.niiwoo.civet.trade.constant.PlatformConstant;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.common.ProjectDynamicDTO;
import com.niiwoo.civet.trade.dto.kaola.NotifyRepaymentResult;
import com.niiwoo.civet.trade.dto.kaola.Result;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.enums.kaola.BadLoansRepayMethodEmun;
import com.niiwoo.civet.trade.enums.kaola.KaoLaLiCaiRepayTypeEnum;
import com.niiwoo.civet.trade.service.local.activity.ActivityEventService;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.civet.trade.service.local.refund.TransDetailLocalService;
import com.niiwoo.civet.trade.service.local.third.ActivityLocalService;
import com.niiwoo.civet.user.dto.request.JPushExtDTO;
import com.niiwoo.civet.user.dto.request.UserLetterRequestDTO;
import com.niiwoo.civet.user.enums.*;
import com.niiwoo.civet.user.service.SendSmsDubboService;
import com.niiwoo.civet.user.service.UserCreditDubboService;
import com.niiwoo.civet.user.service.UserLetterDubboService;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.properties.LanMaoProperties;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service("kaoLaLiCaiRepaymentCallbackService")
@Slf4j
public class KaoLaLiCaiRepaymentCallbackService {

    @Autowired
    private KaoLaRealRepaymentMapperExt kaoLaRealRepaymentMapperExt;

    @Autowired
    private KaoLaOrderInfoMapperExt kaoLaOrderInfoMapperExt;

    @Autowired
    private ProjectMapperExt projectMapperExt;

    @Autowired
    private ProjectBorrowerSummaryMapperExt projectBorrowerSummaryMapperExt;

    @Autowired
    private ProjectBorrowerPlanMapperExt projectBorrowerPlanMapperExt;

    @Autowired
    private KaoLaProjectRepaymentMapperExt kaoLaProjectRepaymentMapperExt;

    @Autowired
    private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;

    @Autowired
    private ProjectCreditorFundMapperExt projectCreditorFundMapper;

    @Autowired
    private ActivityLocalService activityLocalService;

    @Autowired
    private TransDetailLocalService transDetailLocalService;

    @Autowired
    private ProjectLocalService projectLocalService;

    @Reference(version = "1.0.0")
    SendSmsDubboService sendSmsDubboService;

    @Reference(version = "1.0.0")
    UserLetterDubboService userLetterDubboService;


    @Reference(version = "1.0.0")
    BankCardDubboService bankCardDubboService;

    @Reference(version = "1.0.0")
    private UserCreditDubboService userCreditDubboService;

    @Reference(version = "1.0.0")
    private NiiwooBillDubboService niiwooBillDubboService;

    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;

    @Autowired
    KaoLaLiCaiRepaymentService kaoLaLiCaiRepaymentService;


    @Value("${h5-borrow-detail-url}")
    private String h5BorrowDetailUrl;

    @Autowired
    private LanMaoProperties lanMaoProperties;

    @Autowired
    private ActivityEventService activityEventService;

    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财正常还款回调
     */
    @Transactional(rollbackFor = Exception.class)
    public Result nomalRepayCallback(NotifyRepaymentResult repaymentResult) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        Integer period = repaymentResult.getRepay_no();// 还款期数

        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("考拉理财还款回调--项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }

        // 查询项目表信息
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);

        // 查询你我金融还款计划 (0=待还款，1=已经正常还款，2=逾期，3=坏账)
        ProjectBorrowerPlan projectBorrowerPlan = projectBorrowerPlanMapperExt.selectByProjectIdAndPeriodsForUpdate(projectId, period);
        if (projectBorrowerPlan == null) {
            log.info("考拉理财还款回调--未查询到你我金融对应的还款计划!projectId：{},period:{}", projectId, period);
            result.setMessage("未查询到你我金融对应的还款计划!");
            return result;
        }
        // 已正常还款
        if (!projectBorrowerPlan.getRefundStatus().equals(BorrowerPlanRefundStatusEnum.NON_REPAYMENT.getCode())) {
            log.info("考拉理财还款回调--当前还款计划已结清!projectId：{},period:{}", projectId, period);
            result.setMessage("当前还款计划已结清!");
            return result;
        }

        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }

        this.handRefundByPeriod(repaymentResult, summary, projectBorrowerPlan);

        //还款红包返现-借款返现红包
        activityLocalService.useLoancashBackPrize(projectId, null);
        //正常还款useSceneEnum可以为空，提前还款必传
        activityLocalService.useInterestDiscountPrize(projectId, period, null);

        result.setRet(Result.SUCCESS_RET);
        return result;
    }

    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财逾期还款回调(目前只支持还当前期)
     */
    @Transactional(rollbackFor = Exception.class)
    public Result overDueCallback(NotifyRepaymentResult repaymentResult) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        Integer period = repaymentResult.getRepay_no();// 还款期数

        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("考拉理财还款回调--项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }

        // 查询项目表信息
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);

        // 查询你我金融还款计划 (0=待还款，1=已经正常还款，2=逾期，3=坏账)
        ProjectBorrowerPlan projectBorrowerPlan = projectBorrowerPlanMapperExt.selectByProjectIdAndPeriodsForUpdate(projectId, period);
        if (projectBorrowerPlan == null) {
            log.info("考拉理财还款回调--未查询到你我金融对应的还款计划!projectId：{},period:{}", projectId, period);
            result.setMessage("未查询到你我金融对应的还款计划!");
            return result;
        }
        // 已正常还款
        if (!projectBorrowerPlan.getRefundStatus().equals(BorrowerPlanRefundStatusEnum.NON_REPAYMENT.getCode())) {
            log.info("考拉理财还款回调--当前还款计划已结清!projectId：{},period:{}", projectId, period);
            result.setMessage("当前还款计划已结清!");
            return result;
        }
        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }

        //本息相等，全额还款
        this.handlePlanAndCredit(summary, projectBorrowerPlan);

        //本期还完
        this.handOnePeriodRepay(summary, RepayStatusEnum.OVERDUE);

        // 还款流水
        recordSinglePeriodFunddetailForOverDue(repaymentResult, summary, projectBorrowerPlan);

        result.setRet(Result.SUCCESS_RET);
        return result;
    }

    /**
     * （给正常还款使用）
     *
     * @param summary
     * @param projectBorrowerPlan
     */
    protected void handRefundByPeriod(NotifyRepaymentResult repaymentResult, ProjectBorrowerSummary summary, ProjectBorrowerPlan projectBorrowerPlan) {

        //本息相等，全额还款
        this.handlePlanAndCredit(summary, projectBorrowerPlan);

        //本期还完
        this.handOnePeriodRepay(summary, RepayStatusEnum.NORMAL);

        // 还款流水
        recordSingePeriodFunddetail(repaymentResult, summary, projectBorrowerPlan);
    }

    /**
     * 记录还款一期账单流水（给逾期还款使用）
     *
     * @param repaymentResult
     * @param summary
     * @param projectBorrowerPlan
     */
    private void recordSinglePeriodFunddetailForOverDue(NotifyRepaymentResult repaymentResult, ProjectBorrowerSummary summary, ProjectBorrowerPlan projectBorrowerPlan) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);

        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        Integer period = repaymentResult.getRepay_no();// 还款期数
        BigDecimal rechargeAmount = repaymentResult.getAmount().add(repaymentResult.getOverdue_interest());
        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                rechargeAmount, InoutTypeEnum.IN_TYPE, null, null);
        // 充值流水(用户)--充值金额
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, rechargeAmount, BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        // 还款(用户):本金+利息+平台管理费+担保服务费
        AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
        BigDecimal needPayCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());// 应还本金
        BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());// 应还利息
        BigDecimal needPayManageFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());// 应还平台管理费
        BigDecimal needPayGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());// 应还担保服务费
        BigDecimal needPayPenalyFee = projectBorrowerPlan.getPenaltyFee();// 应还罚息
        BigDecimal repaymentAmount = needPayCapital.add(needPayInterest).add(needPayManageFee).add(needPayGuaranteeFee).add(needPayPenalyFee);
        KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                repaymentAmount, InoutTypeEnum.OUT_TYPE, projectId, null);
        // 还款(用户)-本金
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
        }
        // 还款(用户)-利息
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);
        }
        // 还款(用户)-平台管理费
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
        }
        // 还款(用户)-担保服务费
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
        }
        // 还款(用户)-罚息
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
        }
        if (repaymentRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentRequestDTO);
        }

        // 回款(平台)：平台管理费
        AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, repaymentResult.getSerial_no(),
                projectBorrowerPlan.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlan.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, period);
            addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
        }
        if (repaymentForPlatRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentForPlatRequestDTO);
        }

        // 回款(担保公司)：担保服务费+罚息
        AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, repaymentResult.getSerial_no(),
                projectBorrowerPlan.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
        //担保服务费【借】
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
        }
        //垫付罚息回款【借】
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
        }

        //垫付本金回款【借】
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
        }

        //垫付利息回款【借】
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);
        }


        if (guaranteeFeeRequestDTO.getUserId() != null) {
            requestDTOList.add(guaranteeFeeRequestDTO);
        }

        niiwooBillDubboService.addThirdBills(requestDTOList);
    }


    /**
     * 记录还款一期账单流水（给正常还款使用）
     *
     * @param repaymentResult
     * @param summary
     * @param projectBorrowerPlan
     */
    private void recordSingePeriodFunddetail(NotifyRepaymentResult repaymentResult, ProjectBorrowerSummary summary, ProjectBorrowerPlan projectBorrowerPlan) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);

        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        Integer period = repaymentResult.getRepay_no();// 还款期数
        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                repaymentResult.getAmount(), InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, repaymentResult.getAmount(), BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        // 还款(用户):本金+利息+平台管理费+担保服务费
        AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
        BigDecimal needPayCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());// 应还本金
        BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());// 应还利息
        BigDecimal needPayManageFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());// 应还平台管理费
        BigDecimal needPayGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());// 应还担保服务费
        BigDecimal needPayPenalyFee = projectBorrowerPlan.getPenaltyFee();// 应还罚息
        BigDecimal repaymentAmount = needPayCapital.add(needPayInterest).add(needPayManageFee).add(needPayGuaranteeFee).add(needPayPenalyFee);
        KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                repaymentAmount, InoutTypeEnum.OUT_TYPE, projectId, null);
        // 还款(用户)-本金
        if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
        }
        // 还款(用户)-利息
        if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);
        }
        // 还款(用户)-平台管理费
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
        }
        // 还款(用户)-担保服务费
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
        }
        // 还款(用户)-罚息
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, period);
            addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
        }
        if (repaymentRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentRequestDTO);
        }

        // 回款(平台)：平台管理费
        AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, repaymentResult.getSerial_no(),
                projectBorrowerPlan.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
        if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlan.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, period);
            addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
        }
        if (repaymentForPlatRequestDTO.getUserId() != null) {
            requestDTOList.add(repaymentForPlatRequestDTO);
        }

        // 回款(担保公司)：担保服务费+罚息
        AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, repaymentResult.getSerial_no(),
                projectBorrowerPlan.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
        //回款(担保公司)-担保服务费【借】
        if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
        }
        //回款(担保公司)-垫付罚息【借】
        if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
            KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, period);
            addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
        }

        if (guaranteeFeeRequestDTO.getUserId() != null) {
            requestDTOList.add(guaranteeFeeRequestDTO);
        }

        niiwooBillDubboService.addThirdBills(requestDTOList);
    }

    /**
     * （给正常还款和逾期还款使用）修改ProjectBorrowerSummary的费用相关数值（已还总本金、已还总利息、已还平台管理费、已还罚息、已还担保服务费）
     * 和ProjectBorrowerPlan的相关费用（已还总本金、已还总利息、已还平台管理费、已还罚息、已还担保服务费）
     *
     * @param summary
     * @param projectBorrowerPlan
     */
    protected void handlePlanAndCredit(ProjectBorrowerSummary summary, ProjectBorrowerPlan projectBorrowerPlan) {
        ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
        //剩余应还本金
        BigDecimal shouldRefundCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());
        //剩余应还利息
        BigDecimal shouldRefundInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());
        //剩余应还平台管理费
        BigDecimal shouldRefundManagementFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());
        //剩余应还担保服务费
        BigDecimal shouldRefundGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());

        // refunded_corpus已还总本金(累加)
        summaryUpdater.setRefundedCorpus(summary.getRefundedCorpus().add(shouldRefundCapital));
        // refunded_interest 已还总利息(累加)
        summaryUpdater.setRefundedInterest(summary.getRefundedInterest().add(shouldRefundInterest));
        // refunded_management_fee 已还平台管理费(累加)
        summaryUpdater.setRefundedManagementFee(summary.getRefundedManagementFee().add(shouldRefundManagementFee));
        // refunded_penalty_fee 已还罚息(累加)
        summaryUpdater.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));
        //  `refunded_guarantee_fee` 已还担保服务费(累加)
        summaryUpdater.setRefundedGuaranteeFee(summary.getRefundedGuaranteeFee().add(shouldRefundGuaranteeFee));
        summaryUpdater.setProjectId(summary.getProjectId());

        summaryUpdater.setBorrowerUserId(summary.getBorrowerUserId());
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);

        ProjectBorrowerPlan borrowerPlanUpdater = new ProjectBorrowerPlan();
        borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
        //已还本金
        borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
        //已还利息
        borrowerPlanUpdater.setRefundedInterest(projectBorrowerPlan.getInterest());
        //已还罚息
        borrowerPlanUpdater.setRefundedPenaltyFee(projectBorrowerPlan.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));
        //已还平台管理费
        borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
        //已还担保服务费
        borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());
        projectBorrowerPlanMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);


    }


    /**
     * （给正常还款和逾期还款使用）修改ProjectBorrowerPlan的状态（还款状态、结清时间）
     * 和ProjectBorrowerSummary的状态（当前期数、还款状态、应还款日期、自动还款日期）
     *
     * @param summary
     */
    private void handOnePeriodRepay(ProjectBorrowerSummary summary, RepayStatusEnum repayStatusEnumForSummary) {

        //1、还款计划表状态，2、summary期数+1 3、标的状态（最后一期，结清债权）
        ProjectBorrowerPlan projectBorrowerPlan = projectBorrowerPlanMapperExt.selectBorrowerPlanByProjectIdAndCurrentPeriod(summary.getProjectId(), summary.getCurrentPeriod());
        ProjectBorrowerPlan projectBorrowerPlanForUpdate = new ProjectBorrowerPlan();
        projectBorrowerPlanForUpdate.setId(projectBorrowerPlan.getId());
        Byte refundStatusForPlan = repayStatusEnumForSummary == RepayStatusEnum.NORMAL ? BorrowerPlanRefundStatusEnum.NORMAL_REPAYMENT.getCode() : BorrowerPlanRefundStatusEnum.OVERDUE_REPAYMENT.getCode();
        projectBorrowerPlanForUpdate.setRefundStatus(refundStatusForPlan);
        //罚息清零
        projectBorrowerPlanForUpdate.setPenaltyFee(BigDecimal.ZERO);
        projectBorrowerPlanForUpdate.setOverTime(new Date());
        projectBorrowerPlanMapperExt.updateByPrimaryKeySelective(projectBorrowerPlanForUpdate);
        //当期已还
        if (projectBorrowerPlan.getRefundedCapital().add(projectBorrowerPlan.getRefundedInterest()).
                equals(projectBorrowerPlan.getCapital().add(projectBorrowerPlan.getInterest()))) {
            if (summary.getCurrentPeriod().equals(summary.getTotalPeriod())) {
                //最后一期
                ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
                summaryUpdater.setProjectId(summary.getProjectId());
                //还款状态
                summaryUpdater.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
                summaryUpdater.setOverTime(new Date());
                projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);
                Integer nums = projectBorrowerPlanMapperExt.countOverdueNums(summary.getBorrowerUserId(), summary.getProjectId());
                RepayStatusEnum repayStatusEnum = nums > 0 ? RepayStatusEnum.OVERDUE : RepayStatusEnum.NORMAL;
                this.updateProjectStatusForFinish(repayStatusEnum, summary, projectBorrowerPlan);

            } else if (summary.getCurrentPeriod().intValue() < summary.getTotalPeriod()) {
                ProjectBorrowerPlan projectBorrowerPlanForNext = projectBorrowerPlanMapperExt.selectBorrowerPlanByProjectIdAndCurrentPeriod(summary.getProjectId(), summary.getCurrentPeriod() + 1);
                //非最后一期，正常还款
                ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
                summaryUpdater.setPreviousRefundDate(summary.getRefundDate());
                summaryUpdater.setProjectId(summary.getProjectId());
                //当前期数
                summaryUpdater.setCurrentPeriod(summary.getCurrentPeriod() + 1);
                //还款状态
                summaryUpdater.setRepayStatus(RepayStatusEnum.NORMAL.getCode());
                //应还款日期
                summaryUpdater.setRefundDate(projectBorrowerPlanForNext.getRefundDate());
                //自动还款日期
                summaryUpdater.setAutoRefundDate(projectBorrowerPlanForNext.getRefundDate());
                projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);
                this.updateProjectStatusForRepaying(repayStatusEnumForSummary, summary, projectBorrowerPlan);

            }
        } else {
            log.error("handOnePeriodRepay error.");
        }
    }

    /**
     * 添加项目操作动态记录.
     *
     * @param repayStatusEnum
     * @param summary
     * @param plan
     */
    protected void updateProjectStatusForRepaying(RepayStatusEnum repayStatusEnum, ProjectBorrowerSummary summary, ProjectBorrowerPlan plan) {
        ProjectSubStatusEnum projectSubStatusEnum = ProjectSubStatusEnum.REPAYING_INIT;
        switch (repayStatusEnum) {
            //正常还款中
            case NORMAL:
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.REPAYING_NORMAL_TEMPLATE, true);
                break;
            //逾期还款中
            case OVERDUE:
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.REPAYING_OVERDUE_TEMPLATE, true);

                Project projectUpdate = new Project();
                projectUpdate.setProjectId(summary.getProjectId());
                projectUpdate.setSubStatus(ProjectSubStatusEnum.REPAYING_INIT.getSubStatus());
                projectMapperExt.updateByPrimaryKeySelective(projectUpdate);

                break;
            //坏账还款中
            case BADLOANS:
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.REPAYING_BAD_TEMPLATE, true);
                projectSubStatusEnum = ProjectSubStatusEnum.REPAYING_BAD;
                break;
            default:
                break;
        }
        activityEventService.sendProjectStatusChangeEvent(summary.getBorrowerUserId(), new Date(), summary.getProjectId(), ProjectStatusEventEnum.REPAYING, ProjectSubStatusEventEnum.enumOf(projectSubStatusEnum.getSubStatus()));
    }


    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财提前结清还款回调
     */
    @Transactional(rollbackFor = Exception.class)
    public Result settleRepayCallback(NotifyRepaymentResult repaymentResult) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = null;// 项目ID
        projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID

        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("考拉理财还款回调--项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);
        // 已经提前结清
        if (RepayStatusEnum.SETTLEMENT.getCode().equals(summary.getRepayStatus())) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        log.info("考拉还款回调--提前结清回调处理开始,标的号{}", summary.getProjectId());
        this.handleOverDebt(repaymentResult, project, summary);
        //还款红包返现-借款返现红包
        activityLocalService.useLoancashBackPrize(summary.getProjectId(), UserPrizeUseSceneEnum.REPAYMENT_ADVANCE);
        //还款红包返现-借款利率折扣卡
        activityLocalService.useInterestDiscountPrize(summary.getProjectId(), summary.getCurrentPeriod(), UserPrizeUseSceneEnum.REPAYMENT_ADVANCE);

        result.setRet(Result.SUCCESS_RET);
        return result;
    }

    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财严重逾期还款（全部还完）
     */
    @Transactional(rollbackFor = Exception.class)
    public Result settleBadDebtDue(NotifyRepaymentResult repaymentResult, KaoLaRealRepayment kaoLaRealRepayment) throws Exception {
        Result result = new Result(Result.FAIL_RET);
        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID

        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("考拉理财还款回调--项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }
        ProjectBorrowerSummary summary = projectBorrowerSummaryMapperExt.selectByPrimaryKeyForUpdate(projectId);
        // 已结清
        if (RepayStatusEnum.SETTLEMENT.getCode() == summary.getRepayStatus()) {
            log.info("考拉理财还款回调--当前项目已结清!projectId：{}", projectId);
            result.setMessage("当前项目已结清!");
            return result;
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        log.info("考拉还款回调--严重逾期还款（全部还完）回调处理开始,标的号{}", summary.getProjectId());

        //坏账还款拆分类型（1 逾期还款 （第一次还逾期的那一期），2 结清（第二次将坏账那期之后的所有结清））
        if (BadLoansRepayMethodEmun.FRIST_TIME_BAD_DEBT_REPAY.getCode().equals(kaoLaRealRepayment.getBadLoansRepayMethod())) {
            //1 逾期还款 （第一次还逾期的那一期）
            Integer period = repaymentResult.getRepay_no();// 还款期数
            ProjectBorrowerPlan projectBorrowerPlan = projectBorrowerPlanMapperExt.selectByProjectIdAndPeriodsForUpdate(project.getProjectId(), period);
            // 已正常还款
            if (!projectBorrowerPlan.getRefundStatus().equals(BorrowerPlanRefundStatusEnum.NON_REPAYMENT.getCode())) {
                log.info("考拉理财严重逾期还款--第一次还逾期--当前还款计划已结清!projectId：{},period:{}", projectId, period);
                return result;
            }
            fristBadDebtRepay(repaymentResult, project, summary, projectBorrowerPlan);
            if (summary.getCurrentPeriod() < summary.getTotalPeriod()) {
                try {
                    //清偿债权
                    getCurrentProxy().updateCreditorStatus2Settlement(repaymentResult, kaoLaRealRepayment);
                    kaoLaLiCaiRepaymentService.badLoansSettleRepayment(summary);
                } catch (BizException e) {
                    result.setMessage("考拉理财严重逾期还款--第2次还逾期--还款失败.");
                    log.error("考拉理财严重逾期还款--第2次还逾期--还款失败!projectId：{},period:{}", projectId, period, e);
                    //严重逾期-第2次还款失败消息通知（站内信和短信）
                    sendMsgForBadDebtSecondRepayFail(summary.getBorrowerUserId());
                    return result;
                }

            }
        } else if (BadLoansRepayMethodEmun.SECOND_TIME_BAD_DEBT_REPAY.getCode().equals(kaoLaRealRepayment.getBadLoansRepayMethod())) {
            //2 结清（第二次将坏账那期之后的所有结清）
            secondBadDebtRepay(repaymentResult, project, summary);
        }
        result.setRet(Result.SUCCESS_RET);
        return result;
    }


    /**
     * (给提前结清还款用)提前结清
     *
     * @param project
     * @param summary
     */
    private void handleOverDebt(NotifyRepaymentResult repaymentResult, Project project, ProjectBorrowerSummary summary) {

        List<ProjectBorrowerPlan> projectBorrowerPlanList = projectBorrowerPlanMapperExt.selectBorrowerPlanByProjectIdNotRefundProjectId(summary.getProjectId());
        //已还总本金
        BigDecimal refundedCorpus = BigDecimal.ZERO;
        //已还总利息
        BigDecimal refundedInterest = BigDecimal.ZERO;
        //已还罚息
        BigDecimal refundedPenaltyFeeForSummary = BigDecimal.ZERO;
        for (ProjectBorrowerPlan projectBorrowerPlan : projectBorrowerPlanList) {
            ProjectBorrowerPlan borrowerPlanUpdater = new ProjectBorrowerPlan();
            if (projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod())) {
                //已还罚息(原来的已还罚息+待还罚息)
                borrowerPlanUpdater.setRefundedPenaltyFee(projectBorrowerPlan.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));
                //已还利息
                borrowerPlanUpdater.setRefundedInterest(projectBorrowerPlan.getInterest());
                refundedInterest = refundedInterest.add(projectBorrowerPlan.getInterest());
                //已还罚息
                refundedPenaltyFeeForSummary = refundedPenaltyFeeForSummary.add(projectBorrowerPlan.getPenaltyFee());
            }
            borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
            //已还本金
            borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
            //平台管理费
            borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
            //已还担保服务费
            borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());
            //还款状态
            borrowerPlanUpdater.setRefundStatus(BorrowerPlanRefundStatusEnum.OVER_DEBT_REPAYMENT.getCode());
            borrowerPlanUpdater.setOverTime(new Date());
            //改查询方法为累加数据修改
            projectBorrowerPlanMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);
            refundedCorpus = refundedCorpus.add(projectBorrowerPlan.getCapital());
        }


        //考拉的标没有债权关系，也没有投资人相关修改（投资人在考拉端）
        ProjectBorrowerSummary summaryForUpdate = new ProjectBorrowerSummary();
        //已还总本金(累加)
        summaryForUpdate.setRefundedCorpus(summary.getRefundedCorpus().add(refundedCorpus));
        //已还总利息(累加)
        summaryForUpdate.setRefundedInterest(summary.getRefundedInterest().add(refundedInterest));
        //已还平台管理费(设置为平台管理费)
        summaryForUpdate.setRefundedManagementFee(project.getManageFee());
        //已还担保服务费(设置为担保服务费)
        summaryForUpdate.setRefundedGuaranteeFee(project.getGuaranteeFee());
        //已还罚息
        summaryForUpdate.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(refundedPenaltyFeeForSummary));
        summaryForUpdate.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
        summaryForUpdate.setProjectId(project.getProjectId());
        summaryForUpdate.setBorrowerUserId(summary.getBorrowerUserId());
        summaryForUpdate.setOverTime(new Date());
        //该查询方法为累加数据修改
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryForUpdate);

        this.updateProjectStatusForFinish(RepayStatusEnum.SETTLEMENT, summary, null);

        // 添加流水
        recordSettleRepaymentFunddetail(repaymentResult, summary, projectBorrowerPlanList);
    }

    /**
     * 记录提前结清流水
     *
     * @param repaymentResult
     * @param summary
     * @param projectBorrowerPlanList
     */
    private void recordSettleRepaymentFunddetail(NotifyRepaymentResult repaymentResult, ProjectBorrowerSummary summary, List<ProjectBorrowerPlan> projectBorrowerPlanList) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        // 项目ID
        Long projectId = Long.parseLong(repaymentResult.getSubject_id());

        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                repaymentResult.getAmount(), InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, repaymentResult.getAmount(), BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        for (ProjectBorrowerPlan projectBorrowerPlan : projectBorrowerPlanList) {
            // 还款(用户):本金+利息+平台管理费+担保服务费
            AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                    repaymentResult.getAmount(), InoutTypeEnum.OUT_TYPE, projectId, null);

            // 还款(用户)-本金
            BigDecimal needPayCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());// 应还本金
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
            }

            // 还款(用户)-平台管理费
            BigDecimal needPayManageFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());// 应还平台管理费
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
            }

            // 还款(用户)-担保服务费
            BigDecimal needPayGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());// 应还担保服务费
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
            }
            if (repaymentRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentRequestDTO);
            }

            // 回款(平台)：平台管理费
            AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, repaymentResult.getSerial_no(),
                    projectBorrowerPlan.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlan.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
            }
            if (repaymentForPlatRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentForPlatRequestDTO);
            }

            // 回款(担保公司)：担保服务费
            AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, repaymentResult.getSerial_no(),
                    projectBorrowerPlan.getGuaranteeFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                //回款(担保公司)-担保服务费【借】
                KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
            }

            if (projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod())) {
                BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());// 应还利息

                if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
                    // 还款(用户)--还款利息
                    KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, projectBorrowerPlan.getCurrentPeriod());
                    addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);
                }
            }


            if (guaranteeFeeRequestDTO.getUserId() != null) {
                requestDTOList.add(guaranteeFeeRequestDTO);
            }
        }
        niiwooBillDubboService.addThirdBills(requestDTOList);
    }


    private void fristBadDebtRepay(NotifyRepaymentResult repaymentResult, Project project, ProjectBorrowerSummary summary, ProjectBorrowerPlan projectBorrowerPlan) {
        ProjectBorrowerSummary summaryUpdater = new ProjectBorrowerSummary();
        //剩余应还本金
        BigDecimal shouldRefundCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());
        //剩余应还利息
        BigDecimal shouldRefundInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());
        //剩余应还平台管理费
        BigDecimal shouldRefundManagementFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());
        //剩余应还担保服务费
        BigDecimal shouldRefundGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());

        // refunded_corpus已还总本金(累加)
        summaryUpdater.setRefundedCorpus(summary.getRefundedCorpus().add(shouldRefundCapital));
        // refunded_interest 已还总利息(累加)
        summaryUpdater.setRefundedInterest(summary.getRefundedInterest().add(shouldRefundInterest));
        // refunded_management_fee 已还平台管理费(累加)
        summaryUpdater.setRefundedManagementFee(summary.getRefundedManagementFee().add(shouldRefundManagementFee));
        // refunded_penalty_fee 已还罚息(累加)
        summaryUpdater.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));
        //  `refunded_guarantee_fee` 已还担保服务费(累加)
        summaryUpdater.setRefundedGuaranteeFee(summary.getRefundedGuaranteeFee().add(shouldRefundGuaranteeFee));
        summaryUpdater.setProjectId(summary.getProjectId());

        summaryUpdater.setBorrowerUserId(summary.getBorrowerUserId());
        //当期已还
        if (summary.getCurrentPeriod().equals(summary.getTotalPeriod())) {
            //最后一期
            //还款状态
            summaryUpdater.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
            summaryUpdater.setOverTime(new Date());
            this.updateProjectStatusForFinish(RepayStatusEnum.OVERDUE, summary, projectBorrowerPlan);
        }
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryUpdater);

        ProjectBorrowerPlan borrowerPlanUpdater = new ProjectBorrowerPlan();
        borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
        //已还本金
        borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
        //已还利息
        borrowerPlanUpdater.setRefundedInterest(projectBorrowerPlan.getInterest());
        //已还罚息（原来的已还罚息+待还罚息）
        borrowerPlanUpdater.setRefundedPenaltyFee(projectBorrowerPlan.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));
        //已还平台管理费
        borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
        //已还担保服务费
        borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());

        borrowerPlanUpdater.setRefundStatus(BorrowerPlanRefundStatusEnum.OVERDUE_REPAYMENT.getCode());
        //罚息清零
        borrowerPlanUpdater.setPenaltyFee(BigDecimal.ZERO);
        borrowerPlanUpdater.setOverTime(new Date());
        projectBorrowerPlanMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);

        // 还款流水
        recordSinglePeriodFunddetailForOverDue(repaymentResult, summary, projectBorrowerPlan);
    }

    private void secondBadDebtRepay(NotifyRepaymentResult repaymentResult, Project project, ProjectBorrowerSummary summary) {
        List<ProjectBorrowerPlan> projectBorrowerPlanList = projectBorrowerPlanMapperExt.selectBorrowerPlanByProjectIdNotRefundProjectId(summary.getProjectId());
        //已还总本金
        BigDecimal refundedCorpusForSummary = BigDecimal.ZERO;
        //已还总利息
        BigDecimal refundedInterestForSummary = BigDecimal.ZERO;
        //已还罚息
        BigDecimal refundedPenaltyFeeForSummary = BigDecimal.ZERO;
        for (ProjectBorrowerPlan projectBorrowerPlan : projectBorrowerPlanList) {
            ProjectBorrowerPlan borrowerPlanUpdater = new ProjectBorrowerPlan();
            //已还罚息
            borrowerPlanUpdater.setRefundedPenaltyFee(projectBorrowerPlan.getRefundedPenaltyFee().add(projectBorrowerPlan.getPenaltyFee()));

            // 严重逾期需要还两期利息
            if (projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod()) || projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod() + 1)) {
                BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());// 应还利息
                //已还利息
                borrowerPlanUpdater.setRefundedInterest(projectBorrowerPlan.getInterest());
                refundedInterestForSummary = refundedInterestForSummary.add(needPayInterest);
            }
            //summary已还罚息（所有的待还罚息）
            refundedPenaltyFeeForSummary = refundedPenaltyFeeForSummary.add(projectBorrowerPlan.getPenaltyFee());

            borrowerPlanUpdater.setId(projectBorrowerPlan.getId());
            //已还本金
            borrowerPlanUpdater.setRefundedCapital(projectBorrowerPlan.getCapital());
            //平台管理费
            borrowerPlanUpdater.setRefundedManagementFee(projectBorrowerPlan.getManagementFee());
            //已还担保服务费
            borrowerPlanUpdater.setRefundedGuaranteeFee(projectBorrowerPlan.getGuaranteeFee());
            //还款状态
            borrowerPlanUpdater.setRefundStatus(BorrowerPlanRefundStatusEnum.OVERDUE_REPAYMENT.getCode());
            //罚息清零
            borrowerPlanUpdater.setPenaltyFee(BigDecimal.ZERO);
            borrowerPlanUpdater.setOverTime(new Date());
            //改查询方法为累加数据修改
            projectBorrowerPlanMapperExt.updateByPrimaryKeySelective(borrowerPlanUpdater);
            refundedCorpusForSummary = refundedCorpusForSummary.add(projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital()));
        }


        //考拉的标没有债权关系，也没有投资人相关修改（投资人在考拉端）
        ProjectBorrowerSummary summaryForUpdate = new ProjectBorrowerSummary();
        //已还总本金(累加)
        summaryForUpdate.setRefundedCorpus(summary.getRefundedCorpus().add(refundedCorpusForSummary));
        //已还总利息(累加)
        summaryForUpdate.setRefundedInterest(summary.getRefundedInterest().add(refundedInterestForSummary));
        //已还平台管理费(设置为平台管理费)
        summaryForUpdate.setRefundedManagementFee(project.getManageFee());
        //已还担保服务费(设置为担保服务费)
        summaryForUpdate.setRefundedGuaranteeFee(project.getGuaranteeFee());
        //已还罚息
        summaryForUpdate.setRefundedPenaltyFee(summary.getRefundedPenaltyFee().add(refundedPenaltyFeeForSummary));
        summaryForUpdate.setProjectId(project.getProjectId());
        summaryForUpdate.setBorrowerUserId(summary.getBorrowerUserId());
        summaryForUpdate.setRepayStatus(RepayStatusEnum.SETTLEMENT.getCode());
        summaryForUpdate.setOverTime(new Date());
        //该查询方法为累加数据修改
        projectBorrowerSummaryMapperExt.updateByPrimaryKeySelective(summaryForUpdate);

        this.updateProjectStatusForFinish(RepayStatusEnum.BADLOANS, summary, null);

        // 添加流水
        recordBadDebtFunddetail(repaymentResult, summary, projectBorrowerPlanList);
    }

    /**
     * 记录严重逾期还款流水
     *
     * @param repaymentResult
     * @param summary
     * @param projectBorrowerPlanList
     */
    private void recordBadDebtFunddetail(NotifyRepaymentResult repaymentResult, ProjectBorrowerSummary summary, List<ProjectBorrowerPlan> projectBorrowerPlanList) {
        // 平台账户
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        // 项目ID
        Long projectId = Long.parseLong(repaymentResult.getSubject_id());
        BigDecimal rechargeAmount = repaymentResult.getAmount().add(repaymentResult.getOverdue_interest());

        // 充值流水(用户)
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO rechargeRequestDTO = new AddThirdBillRequestDTO();
        //充值流水(用户)--充值金额
        KaoLaBill rechargeBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                rechargeAmount, InoutTypeEnum.IN_TYPE, null, null);
        KaolaDetailBill rechargeBillDetail = new KaolaDetailBill(null, rechargeAmount, BillSecondSubjectEnum.USER_RECHARGE, null);
        addKaoLaBill(rechargeRequestDTO, rechargeBill, rechargeBillDetail);
        requestDTOList.add(rechargeRequestDTO);

        for (ProjectBorrowerPlan projectBorrowerPlan : projectBorrowerPlanList) {
            // 还款(用户):本金+利息+平台管理费+担保服务费
            AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentRequestBill = new KaoLaBill(summary.getBorrowerUserId(), BillUserTypeEnum.GENERAL, repaymentResult.getSerial_no(),
                    repaymentResult.getAmount(), InoutTypeEnum.OUT_TYPE, projectId, null);

            // 还款(用户)-本金
            BigDecimal needPayCapital = projectBorrowerPlan.getCapital().subtract(projectBorrowerPlan.getRefundedCapital());// 应还本金
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill princialBillDetail = new KaolaDetailBill(null, needPayCapital, BillSecondSubjectEnum.USER_REPAYMENT_CORPUS, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, princialBillDetail);
            }

            // 还款(用户)-平台管理费
            BigDecimal needPayManageFee = projectBorrowerPlan.getManagementFee().subtract(projectBorrowerPlan.getRefundedManagementFee());// 应还平台管理费
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill manageFeeBillDetail = new KaolaDetailBill(accountBase.getUserId(), needPayManageFee, BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, manageFeeBillDetail);
            }

            // 还款(用户)-担保服务费
            BigDecimal needPayGuaranteeFee = projectBorrowerPlan.getGuaranteeFee().subtract(projectBorrowerPlan.getRefundedGuaranteeFee());// 应还担保服务费
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, guaranteeFeeBillDetail);
            }

            // 还款(用户)-罚息
            BigDecimal needPayPenalyFee = projectBorrowerPlan.getPenaltyFee();// 应还罚息
            if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill penalyFeeBillDetail = new KaolaDetailBill(this.getGuaranteeUserId(), needPayPenalyFee, BillSecondSubjectEnum.USER_REPAYMENT_PENALTY, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, penalyFeeBillDetail);
            }
            if (repaymentRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentRequestDTO);
            }

            // 回款(平台)：平台管理费
            AddThirdBillRequestDTO repaymentForPlatRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill repaymentForPlatRequestBill = new KaoLaBill(accountBase.getUserId(), BillUserTypeEnum.PLATFORM, repaymentResult.getSerial_no(),
                    projectBorrowerPlan.getManagementFee(), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayManageFee.compareTo(BigDecimal.ZERO) > 0) {
                //回款(平台)-平台管理费【极速借】
                KaolaDetailBill repaymentForPlatRequestBillDtl = new KaolaDetailBill(summary.getBorrowerUserId(), projectBorrowerPlan.getManagementFee(), BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(repaymentForPlatRequestDTO, repaymentForPlatRequestBill, repaymentForPlatRequestBillDtl);
            }
            if (repaymentForPlatRequestDTO.getUserId() != null) {
                requestDTOList.add(repaymentForPlatRequestDTO);
            }

            // 回款(担保公司)：担保服务费
            AddThirdBillRequestDTO guaranteeFeeRequestDTO = new AddThirdBillRequestDTO();
            KaoLaBill guaranteeFeeRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, repaymentResult.getSerial_no(),
                    projectBorrowerPlan.getGuaranteeFee().add(needPayPenalyFee), InoutTypeEnum.IN_TYPE, projectId, null);
            if (needPayGuaranteeFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranteeFeeRequestBillDtl = new KaolaDetailBill(this.getGuaranteeUserId(), needPayGuaranteeFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranteeFeeRequestBillDtl);
            }
            //回款(担保公司)-垫付罚息回款【借】
            if (needPayPenalyFee.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill guaranTeePenalyFeeBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayPenalyFee, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, guaranTeePenalyFeeBillDetail);
            }
            //回款(担保公司)-垫付本金回款【借】
            if (needPayCapital.compareTo(BigDecimal.ZERO) > 0) {
                KaolaDetailBill advanceCapitalBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayCapital, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL, projectBorrowerPlan.getCurrentPeriod());
                addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceCapitalBackBillDetail);
            }

            // 严重逾期需要还两期利息
            if (projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod()) || projectBorrowerPlan.getCurrentPeriod().equals(summary.getCurrentPeriod() + 1)) {
                BigDecimal needPayInterest = projectBorrowerPlan.getInterest().subtract(projectBorrowerPlan.getRefundedInterest());// 应还利息
                if (needPayInterest.compareTo(BigDecimal.ZERO) > 0) {
                    // 还款(用户)--还款利息
                    KaolaDetailBill interestBillDetail = new KaolaDetailBill(null, needPayInterest, BillSecondSubjectEnum.USER_REPAYMENT_INTEREST, projectBorrowerPlan.getCurrentPeriod());
                    addKaoLaBill(repaymentRequestDTO, repaymentRequestBill, interestBillDetail);

                    // 回款(担保公司)---垫付利息回款【借】
                    KaolaDetailBill advanceInterestBackBillDetail = new KaolaDetailBill(summary.getBorrowerUserId(), needPayInterest, BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST, projectBorrowerPlan.getCurrentPeriod());
                    addKaoLaBill(guaranteeFeeRequestDTO, guaranteeFeeRequestBill, advanceInterestBackBillDetail);
                }
            }

            if (guaranteeFeeRequestDTO.getUserId() != null) {
                requestDTOList.add(guaranteeFeeRequestDTO);
            }

        }
        niiwooBillDubboService.addThirdBills(requestDTOList);
    }

    /**
     * 修改Project的状态，插入项目操作记录
     *
     * @param repayStatusEnum
     * @param summary
     * @param plan
     */
    protected void updateProjectStatusForFinish(RepayStatusEnum repayStatusEnum, ProjectBorrowerSummary summary, ProjectBorrowerPlan plan) {
        Project projectUpdate = new Project();
        projectUpdate.setProjectId(summary.getProjectId());
        try {
            userCreditDubboService.changeCreditNeedUpdate(summary.getBorrowerUserId(), CreditEnum.CreditAmountType.SPEED_BORROW);
        } catch (Exception e) {
            log.error("userCreditDubboService.changeCreditNeedUpdate() error", e);
        }
        switch (repayStatusEnum) {
            //正常结清
            case NORMAL:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_NORMAL.getSubStatus());
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.FINISH_NORMAL, false);
                break;
            //逾期还款结清
            case OVERDUE:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_OVERDUE.getSubStatus());
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.FINISH_OVERDUE, false);
                break;
            //坏账结清
            case BADLOANS:
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_BAD.getSubStatus());
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.FINISH_OVERDUE, false);
                break;
            default://提前结清
                projectUpdate.setSubStatus(ProjectSubStatusEnum.FINISH_ADVANCE.getSubStatus());
                this.addProjectRecord(summary, plan, ProjectDynamicEnum.FINISH_ADVANCE, false);

                break;
        }
        projectUpdate.setStatus(ProjectStatusEnum.FINISH.getStatus());
        projectMapperExt.updateByPrimaryKeySelective(projectUpdate);
        activityEventService.sendProjectStatusChangeEvent(summary.getBorrowerUserId(), new Date(), summary.getProjectId(), ProjectStatusEventEnum.FINISH, ProjectSubStatusEventEnum.enumOf(projectUpdate.getSubStatus()));
    }

    /**
     * 添加项目操作动态记录
     *
     * @param summary
     * @param plan
     * @param projectDynamicEnum
     * @param hasFeeDetail
     */
    private void addProjectRecord(ProjectBorrowerSummary summary, ProjectBorrowerPlan plan, ProjectDynamicEnum projectDynamicEnum, boolean hasFeeDetail) {
        ProjectDynamicDTO dto = new ProjectDynamicDTO();
        dto.setProjectId(summary.getProjectId());
        dto.setRelationId(plan == null ? null : plan.getId());
        dto.setTradeTypeEnum(ProjectDynamicDTO.TradeTypeEnum.REPAYMENT);
        dto.setProjectDynamicEnum(projectDynamicEnum);
        dto.setUserId(summary.getBorrowerUserId());
        if (hasFeeDetail) {
            List<String> paramsList = new ArrayList<>();
            paramsList.add(plan.getRefundedGuaranteeFee().add(plan.getRefundedManagementFee()).add(plan.getRefundedPenaltyFee()).add(plan.getRefundedInterest()).add(plan.getRefundedCapital()).toString());
            if (plan.getRefundedGuaranteeFee().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("担保服务费" + plan.getRefundedGuaranteeFee());
            }
            if (plan.getRefundedManagementFee().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("平台管理费" + plan.getRefundedManagementFee());
            }
            if (plan.getRefundedInterest().compareTo(BigDecimal.ZERO) > 0) {
                paramsList.add("罚息" + plan.getRefundedPenaltyFee());
            }
            paramsList.add("利息" + plan.getRefundedInterest());
            paramsList.add("本金" + plan.getRefundedCapital());
            dto.setParamsList(paramsList);
        }

        projectLocalService.addProjectDynamicRecord(dto);
    }


    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财垫付还款回调
     */
    public Result advanceRepayCallback(NotifyRepaymentResult repaymentResult) {
        Result result = new Result(Result.FAIL_RET);

        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        Integer period = repaymentResult.getRepay_no();// 还款期数

        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }

        // 查询项目表信息
        Project project = this.projectMapperExt.selectByPrimaryKeyForUpdate(projectId);
        if (project == null) {
            log.info("未查询到你我金融对应的项目信息!projectId：{}", projectId);
            result.setMessage("未查询到你我金融对应的项目信息!");
            return result;
        }

        // 查询考拉理财还款计划
        KaoLaProjectRepayment kaoLaProjectRepayment = kaoLaProjectRepaymentMapperExt.selectByProjectIdAndPeriod(projectId, period);
        if (kaoLaProjectRepayment == null) {
            log.info("未查询到考拉理财对应的还款计划!projectId：{},period:{}", projectId, period);
            result.setMessage("未查询到考拉理财对应的还款计划!");
        }

        //考拉垫付的利息
        BigDecimal interest = repaymentResult.getInterest().subtract(repaymentResult.getInterest_split());
        //考拉垫付的总金额
        BigDecimal amount = repaymentResult.getPrincipal().add(interest);

        // 记代偿流水（代偿后走逾期还款流程）
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO repaymentRequestDTO = new AddThirdBillRequestDTO();
        repaymentRequestDTO.setUserId(this.getGuaranteeUserId());
        repaymentRequestDTO.setBillType(BillUserTypeEnum.GUARANTEE_AGENCY);
        repaymentRequestDTO.setRequestNo(repaymentResult.getSerial_no());
        repaymentRequestDTO.setAmount(amount);
        repaymentRequestDTO.setInoutType(InoutTypeEnum.OUT_TYPE);
        repaymentRequestDTO.setProjectId(projectId);
        repaymentRequestDTO.setChannelCodeEnum(com.niiwoo.civet.base.enums.ChannelCodeEnum.KAOLA);
        repaymentRequestDTO.setRemark(null);
        repaymentRequestDTO.setBillDetailList(new ArrayList<>());

        // 账单明细表--本金
        AddThirdBillRequestDTO.BillDetail billDetailForPrincial = repaymentRequestDTO.genertBillDetailInstance();
        billDetailForPrincial.setRelationUserId(null);
        billDetailForPrincial.setAmount(repaymentResult.getPrincipal());
        billDetailForPrincial.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_PRINCIPAL_SPEED_BORROW);
        billDetailForPrincial.setCurrentPeriod(period);
        repaymentRequestDTO.getBillDetailList().add(billDetailForPrincial);

        // 账单明细表--利息
        AddThirdBillRequestDTO.BillDetail billDetailForInterest = repaymentRequestDTO.genertBillDetailInstance();
        billDetailForInterest.setRelationUserId(null);
        billDetailForInterest.setAmount(interest);
        billDetailForInterest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_INTEREST);
        billDetailForInterest.setCurrentPeriod(period);
        repaymentRequestDTO.getBillDetailList().add(billDetailForInterest);

        requestDTOList.add(repaymentRequestDTO);
        niiwooBillDubboService.addThirdBills(requestDTOList);

        result.setRet(Result.SUCCESS_RET);
        return result;
    }

    /**
     * @param repaymentResult
     * @return Result
     * @Description 考拉理财回购回调
     */
    @Transactional(rollbackFor = Exception.class)
    public Result buyBackCallback(NotifyRepaymentResult repaymentResult) throws Exception {
        Result result = new Result(Result.FAIL_RET);

        Long projectId = Long.parseLong(repaymentResult.getSubject_id());// 项目ID
        // 判断考拉订单信息是否存在
        KaoLaOrderInfo kaoLaOrderInfo = kaoLaOrderInfoMapperExt.selectByProjectId(projectId);
        if (StringUtils.isBlank(kaoLaOrderInfo.getLoanOrderId())) {
            log.info("项目异常，不能发送查询请求！projectId：{}", projectId);
            result.setFailureMessage("项目异常，不能发送查询请求！");
            return result;
        }

        // 查询项目表信息
        Project project = projectMapperExt.selectByPrimaryKeyForUpdate(projectId);
        if (project == null) {
            log.info("未查询到你我金融对应的项目信息!projectId：{}", projectId);
            result.setMessage("未查询到你我金融对应的项目信息!");
            return result;
        }

        // 记代偿流水（代偿后走逾期还款流程）
        List<AddThirdBillRequestDTO> requestDTOList = new ArrayList<>();
        AddThirdBillRequestDTO buyBackRequestDTO = new AddThirdBillRequestDTO();
        KaoLaBill advanceRequestBill = new KaoLaBill(this.getGuaranteeUserId(), BillUserTypeEnum.GUARANTEE_AGENCY, repaymentResult.getSerial_no(),
                repaymentResult.getAmount(), InoutTypeEnum.OUT_TYPE, projectId, null);
        KaolaDetailBill buyBackBillDetail = new KaolaDetailBill(null, repaymentResult.getAmount(), BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_BYBACK, null);
        addKaoLaBill(buyBackRequestDTO, advanceRequestBill, buyBackBillDetail);
        requestDTOList.add(buyBackRequestDTO);
        niiwooBillDubboService.addThirdBills(requestDTOList);

        result.setRet(Result.SUCCESS_RET);
        return result;
    }


    /**
     * @param repaymentResult
     * @return Result
     * @throws Exception
     * @Description 发送还款失败消息
     */
    public Result sendRepaymentFailMessage(NotifyRepaymentResult repaymentResult) throws Exception {
        Result result = new Result(Result.SUCCESS_RET);
        // 项目
        Project project = projectMapperExt.selectByPrimaryKey(Long.parseLong(repaymentResult.getSubject_id()));
        if (null == project) {
            log.info("未查询到你我金融对应的项目信息!projectId：{}", repaymentResult.getSubject_id());
            result.setFailureMessage("未查询到你我金融对应的项目信息!");
            return result;
        }

        // 当前有效银行卡
        BankCardDTO bankCardDTO = bankCardDubboService.getUserBankCardInfo(project.getBorrowUserId());
        if (null == bankCardDTO) {
            log.info("未查询到用户有效银行卡信息!userId：{}", project.getBorrowUserId());
            result.setMessage("未查询到用户有效银行卡信息!");
            return result;
        }
        String bankAcccount = bankCardDTO.getBankAccountNo();// 银行卡账户
        // 银行卡账户是否为空
        if (StringUtils.isBlank(bankAcccount)) {
            log.info("未查询到用户有效银行卡信息!userId：{}", project.getBorrowUserId());
            result.setMessage("未查询到用户有效银行卡信息!");
            return result;
        }
        // 银行卡后四位
        String suffixBankAccount = bankAcccount.substring(bankAcccount.length() - 4,
                bankAcccount.length());

        String amount = repaymentResult.getAmount().add(repaymentResult.getOverdue_interest()).setScale(2, BigDecimal.ROUND_HALF_EVEN).toString();

        if (repaymentResult.getMsg() != null && KaolaRepayFailMessageList.isContainMessageList(repaymentResult.getMsg())) {
            amount = amount + ",具体原因如下:\"" + repaymentResult.getMsg() + "\"";
        }

        // 项目ID，项目标题，银行卡号，欠款金额
        String[] msgParams = {project.getProjectId().toString(), suffixBankAccount, amount};
        List<Object> listForParams = Arrays.asList(msgParams);
        try {
            this.sendMsgForKaolaRepaymentFail(project.getBorrowUserId(), listForParams);
        } catch (Exception e) {
            log.error("还款回调失败发送短信sendMsgForKaolaRepaymentFail-error", e);
        }
        return result;
    }

    /**
     * @param userId
     * @param params
     * @throws Exception
     */
    public void sendMsgForKaolaRepaymentFail(String userId, List<Object> params) throws Exception {
        //发送短信
        sendSmsDubboService.sendSmsByUserId(userId, SMSTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL.getKey(), params);

        //发送站内信
        UserLetterRequestDTO userLetterRequestDTO = new UserLetterRequestDTO();
        userLetterRequestDTO.setToUserId(userId);
        userLetterRequestDTO.setUserLetterTypeEnum(UserLetterTypeEnum.LETTER_AND_JPUSH);

        //您好，您的借款项目【<a href="http://test.niiwoo.com:5006/h5/app/project/my_details/#/loandt?ProjectId={0}">{1}</a>】还款失败，请保证尾号{2}银行卡余额大于{3}，登录你我金融再次发起还款，如有疑问请联系钱小二。
        String hrefTemp = "<a href=\"%s\">%s</a>";
        String[] arrayForHref = new String[]{h5BorrowDetailUrl + params.get(0), params.get(0).toString()};
        String hrefContent = String.format(hrefTemp, arrayForHref);
        //站内信
        List<Object> paramsForLetter = new ArrayList<>(params);
        paramsForLetter.set(0, hrefContent);
        userLetterRequestDTO.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL);
        userLetterRequestDTO.setLetterTemplateParamList(paramsForLetter);
        //极光推送
        userLetterRequestDTO.setJpushTemplateKeyEnum(MessageTemplateKeyEnum.JPushTemplateKeyEnum.TEMP_KAOLALICAI_REPAYMENT_FAIL);
        userLetterRequestDTO.setJpushTemplateParamList(params);
        JPushExtDTO jPushExtDTO = new JPushExtDTO();
        jPushExtDTO.setRedirectPageEnum(JPushEnum.RedirectPageEnum.NOTICE_LIST_PAGE);
        userLetterRequestDTO.setJPushExt(jPushExtDTO);
        userLetterDubboService.pushLetter(userLetterRequestDTO);
    }

    /**
     * 严重逾期-第2次还款失败消息通知（站内信和短信）
     *
     * @param userId
     * @param params
     * @throws Exception
     */
    public void sendMsgForBadDebtSecondRepayFail(String userId) {
        try {
            //由于代扣问题，部分还款成功，剩余未还金额，请重新操作还款。由此给您带来不便，敬请谅解,如有疑问请联系钱小二。
            //发送短信
            sendSmsDubboService.sendSmsByUserId(userId, SMSTemplateKeyEnum.TEMP_KAOLALICAI_BAD_DEBT_SECOND_REPAYMENT_FAIL.getKey(), null);

            //发送站内信
            UserLetterRequestDTO userLetterRequestDTO = new UserLetterRequestDTO();
            userLetterRequestDTO.setToUserId(userId);
            userLetterRequestDTO.setUserLetterTypeEnum(UserLetterTypeEnum.ONLY_LETTER);
            //站内信
            userLetterRequestDTO.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.TEMP_KAOLALICAI_BAD_DEBT_SECOND_REPAYMENT_FAIL);
            userLetterDubboService.pushLetter(userLetterRequestDTO);

        } catch (Exception e) {
            log.error("严重逾期-第2次还款失败消息通知（站内信和短信）-还款回调失败发送短信sendMsgForSecondBadDebtRepayFail-error", e);
        }
    }

    private KaoLaLiCaiRepaymentCallbackService getCurrentProxy() {
        return (KaoLaLiCaiRepaymentCallbackService) AopContext.currentProxy();
    }

    /**
     * 成功时除了代偿和回购其他的都要算清偿债权.
     *
     * @param repaymentResult 回调通知
     * @param klRepayment     实际还款记录
     */
    public void updateCreditorStatus2Settlement(NotifyRepaymentResult repaymentResult, KaoLaRealRepayment klRepayment) {
        ProjectCreditorFund creditorFund = new ProjectCreditorFund();
        creditorFund.setProjectId(klRepayment.getProjectId());
        if (!(KaoLaLiCaiRepayTypeEnum.REPAY_ADVANCE.getCode().equals(repaymentResult.getType())
                || KaoLaLiCaiRepayTypeEnum.REPAY_BUYBACK.getCode().equals(repaymentResult.getType()))) {

            boolean notSettleOrBadDebt = !(KaoLaLiCaiRepayTypeEnum.REPAY_SETTLE.getCode().equals(repaymentResult.getType()) || (KaoLaLiCaiRepayTypeEnum
                    .REPAY_OVERDUE.getCode().equals(repaymentResult.getType()) && klRepayment.getRepayMethod().equals
                    (KaoLaRealRepayment.RepayMethodEnum.BAD_DEBT_REPAY.getType())
                    && klRepayment.getBadLoansRepayMethod().equals(BadLoansRepayMethodEmun.SECOND_TIME_BAD_DEBT_REPAY.getCode())));

            //不是提前结清或坏账还款则只更新当前期
            if (notSettleOrBadDebt) {
                if (Objects.isNull(klRepayment.getRepayNo())) {
                    creditorFund.setCurrentPeriod(100);
                    log.error("考拉还款回调处理异常! 非结清的场景当前期为空,repayType:[{}]", repaymentResult.getType());
                }
                creditorFund.setCurrentPeriod(klRepayment.getRepayNo());
            }
            projectCreditorFundMapper.updateCreditorStatus2Settlement(creditorFund);
        }
    }

    /**
     * 获取担保公司userId
     *
     * @return
     */
    private String getGuaranteeUserId() {
        return "" + lanMaoProperties.getNiiWooAccount().getGuaranteeUserId();
    }


    /**
     * 添加考拉账单
     *
     * @param kaoLaBill
     * @return
     */
    private void addKaoLaBill(AddThirdBillRequestDTO thirdBillRequestDTO, KaoLaBill kaoLaBill, KaolaDetailBill kaolaDetailBill) {
        // 账单主表，判断是否已赋值
        if (thirdBillRequestDTO.getUserId() == null) {
            thirdBillRequestDTO.setUserId(kaoLaBill.getUserId());
            thirdBillRequestDTO.setBillType(kaoLaBill.getBillUserTypeEnum());
            thirdBillRequestDTO.setRequestNo(kaoLaBill.getRequestNo());
            thirdBillRequestDTO.setAmount(kaoLaBill.getAmount());
            thirdBillRequestDTO.setInoutType(kaoLaBill.getInoutType());
            thirdBillRequestDTO.setProjectId(kaoLaBill.getProjectId());
            thirdBillRequestDTO.setChannelCodeEnum(com.niiwoo.civet.base.enums.ChannelCodeEnum.KAOLA);
            thirdBillRequestDTO.setRemark(kaoLaBill.getRemark());
        }

        // 账单明细表
        AddThirdBillRequestDTO.BillDetail billDetail = thirdBillRequestDTO.genertBillDetailInstance();
        billDetail.setRelationUserId(kaolaDetailBill.getUserId());
        billDetail.setAmount(kaolaDetailBill.getAmount());
        billDetail.setBillSecondSubjectEnum(kaolaDetailBill.getBillSecondSubjectEnum());
        billDetail.setCurrentPeriod(kaolaDetailBill.getCurrentPeriod());

        List<AddThirdBillRequestDTO.BillDetail> billDetailList = thirdBillRequestDTO.getBillDetailList();
        if (billDetailList == null) {
            thirdBillRequestDTO.setBillDetailList(new ArrayList<>());
        }
        thirdBillRequestDTO.getBillDetailList().add(billDetail);
    }

    @Setter
    @Getter
    @AllArgsConstructor
    private static class KaoLaBill {
        private String userId;// 用户
        private BillUserTypeEnum billUserTypeEnum;//账单用户类型枚举
        private String requestNo;//请求流水
        private BigDecimal amount;// 金额
        private InoutTypeEnum inoutType;// 收支类型
        private Long projectId;//项目ID
        private String remark;// 描述
    }

    @Setter
    @Getter
    @AllArgsConstructor
    private static class KaolaDetailBill {
        private String userId;// 关联用户
        private BigDecimal amount;// 金额
        private BillSecondSubjectEnum billSecondSubjectEnum;//账单二级类型
        private Integer currentPeriod;//当前期数
    }



}

